package beanstao.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.Writer;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Queue;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.lang.time.StopWatch;

import beanstao.util.collections.interfaces.IEach;
import beanstao.util.exception.base.AppException;
import beanstao.util.exception.technical.util.ExitLoopException;
import beanstao.util.exception.technical.util.LoopException;
import beanstao.util.exception.technical.util.reflect.FailToCastObjectException;
import beanstao.util.io.Streams;
import beanstao.util.io.StringInputStream;
import beanstao.util.io.StringOutputStream;
import beanstao.util.io.StringReader;
import beanstao.util.io.StringWriter;
import beanstao.util.reflect.Mirror;
import beanstao.util.type.Castors;

/**
 * Java的一些不易归类的静态方法集。 这些帮助函数让 Java 的某些常用功能变得更简单。
 * 
 * @author beanstao@google.com 
 */
public abstract class Util
{
	/**
	 * 较方便的创建一个数组，比如：
	 * 
	 * <pre>
	 * Pet[] pets = Util.array(pet1, pet2, pet3);
	 * </pre>
	 * 
	 * @param eles 可变参数
	 * @return 数组对象
	 */
	public static <T> T[] array(final T... eles)
	{
		return eles;
	}

	/**
	 * 将数组转换成另外一种类型的数组。将会采用 Castor 来深层转换数组元素
	 * 
	 * @param array 原始数组
	 * @param eleType 新数组的元素类型
	 * @return 新数组
	 * @throws FailToCastObjectException .castor.Castors
	 */
	public static Object array2array(final Object array, final Class<?> eleType) throws FailToCastObjectException
	{
		if (null == array)
			return null;
		int len = Array.getLength(array);
		Object re = Array.newInstance(eleType, len);
		for (int i = 0; i < len; i++)
			Array.set(re, i, Castors.me().castTo(Array.get(array, i), eleType));
		return re;
	}

	/**
	 * 将一个数组变成 Map
	 * 
	 * @param mapClass Map 的类型
	 * @param array 数组
	 * @param keyFieldName 采用集合中元素的哪个一个字段为键。
	 * @return Map 对象
	 */
	public static <T extends Map<Object, Object>> Map<?, ?> array2map(final Class<T> mapClass, final Object array, final String keyFieldName)
	{
		if (null == array)
			return null;
		Map<Object, Object> map = createMap(mapClass);
		int len = Array.getLength(array);
		if (len > 0)
		{
			Object obj = Array.get(array, 0);
			Mirror<?> mirror = Mirror.me(obj.getClass());
			for (int i = 0; i < len; i++)
			{
				obj = Array.get(array, i);
				Object key = mirror.getValue(obj, keyFieldName);
				map.put(key, obj);
			}
		}
		return map;
	}

	/**
	 * 将数组转换成Object[] 数组。将会采用 Castor 来深层转换数组元素
	 * 
	 * @param args 原始数组
	 * @param pts 新数组的元素类型
	 * @return 新数组
	 * @throws FailToCastObjectException .castor.Castors
	 */
	public static <T> Object[] array2ObjectArray(final T[] args, final Class<?>[] pts) throws FailToCastObjectException
	{
		if (null == args)
			return null;
		Object[] newArgs = new Object[args.length];
		for (int i = 0; i < args.length; i++)
			newArgs[i] = Castors.me().castTo(args[i], pts[i]);
		return newArgs;
	}

	/**
	 * 将一个对象添加成为一个数组的第一个元素，从而生成一个新的数组
	 * 
	 * @param e 对象
	 * @param eles 数组
	 * @return 新数组
	 */
	@SuppressWarnings("unchecked")
	public static <T> T[] arrayFirst(final T e, final T[] eles)
	{
		try
		{
			if ((null == eles) || (eles.length == 0))
			{
				T[] arr = (T[]) Array.newInstance(e.getClass(), 1);
				arr[0] = e;
				return arr;
			}
			T[] arr = (T[]) Array.newInstance(eles.getClass().getComponentType(), eles.length + 1);
			arr[0] = e;
			for (int i = 0; i < eles.length; i++)
				arr[i + 1] = eles[i];
			return arr;
		}
		catch (NegativeArraySizeException e1)
		{
			throw Util.wrapThrow(e1);
		}
	}

	/**
	 * 将一个对象添加成为一个数组的最后一个元素，从而生成一个新的数组
	 * 
	 * @param e 对象
	 * @param eles 数组
	 * @return 新数组
	 */
	@SuppressWarnings("unchecked")
	public static <T> T[] arrayLast(final T[] eles, final T e)
	{
		try
		{
			if ((null == eles) || (eles.length == 0))
			{
				T[] arr = (T[]) Array.newInstance(e.getClass(), 1);
				arr[0] = e;
				return arr;
			}
			T[] arr = (T[]) Array.newInstance(eles.getClass().getComponentType(), eles.length + 1);
			for (int i = 0; i < eles.length; i++)
				arr[i] = eles[i];
			arr[eles.length] = e;
			return arr;
		}
		catch (NegativeArraySizeException e1)
		{
			throw Util.wrapThrow(e1);
		}
	}

	/**
	 * 将集合变成指定类型的数组
	 * 
	 * @param coll 集合对象
	 * @param eleType 数组元素类型
	 * @return 数组
	 */
	public static Object collection2array(final Collection<?> coll, final Class<?> eleType)
	{
		if (null == coll)
			return null;
		Object re = Array.newInstance(eleType, coll.size());
		int i = 0;
		for (Object name : coll)
			Array.set(re, i++, name);
		return re;
	}

	/**
	 * 将集合变成数组，数组的类型为集合的第一个元素的类型。如果集合为空，则返回 null
	 * 
	 * @param coll 集合对象
	 * @return 数组
	 */
	@SuppressWarnings("unchecked")
	public static <E> Object collection2array(final Collection<E> coll)
	{
		if ((null == coll) || (coll.size() == 0))
			return null;
		Class<E> eleType = (Class<E>) Util.first(coll).getClass();
		return collection2array(coll, eleType);
	}

	/**
	 * 将集合变成 ArrayList
	 * 
	 * @param coll 集合对象
	 * @return 列表对象
	 */
	public static <E> List<E> collection2list(final Collection<E> coll)
	{
		return collection2list(coll, null);
	}

	/**
	 * 将集合编程变成指定类型的列表
	 * 
	 * @param coll 集合对象
	 * @param classOfList 列表类型
	 * @return 列表对象
	 */
	public static <E> List<E> collection2list(final Collection<E> coll, final Class<List<E>> classOfList)
	{
		if (coll instanceof List<?>)
			return (List<E>) coll;
		List<E> list;
		try
		{
			list = (null == classOfList ? new ArrayList<E>(coll.size()) : classOfList.newInstance());
		}
		catch (Exception e)
		{
			throw Util.wrapThrow(e);
		}
		for (E e : coll)
			list.add(e);
		return list;
	}

	/**
	 * 将一个集合变成 Map。
	 * 
	 * @param mapClass Map 的类型
	 * @param coll 集合对象
	 * @param keyFieldName 采用集合中元素的哪个一个字段为键。
	 * @return Map 对象
	 */
	public static <T extends Map<Object, Object>> Map<?, ?> collection2map(final Class<T> mapClass, final Collection<?> coll, final String keyFieldName)
	{
		if (null == coll)
			return null;
		Map<Object, Object> map = createMap(mapClass);
		if (coll.size() > 0)
		{
			Iterator<?> it = coll.iterator();
			Object obj = it.next();
			Mirror<?> mirror = Mirror.me(obj.getClass());
			Object key = mirror.getValue(obj, keyFieldName);
			map.put(key, obj);
			for (; it.hasNext();)
			{
				obj = it.next();
				key = mirror.getValue(obj, keyFieldName);
				map.put(key, obj);
			}
		}
		return map;
	}

	/**
	 * 将一个数组的部分元素转换成字符串
	 * <p>
	 * 每个元素之间，都会用一个给定的字符分隔
	 * 
	 * @param offset 开始元素的下标
	 * @param len 元素数量
	 * @param c 分隔符
	 * @param objs 数组
	 * @return 拼合后的字符串
	 */
	public static <T> StringBuilder concat(final int offset, final int len, final Object c, final T[] objs)
	{
		StringBuilder sb = new StringBuilder();
		if ((null == objs) || (len < 0) || (0 == objs.length))
			return sb;

		if (offset < objs.length)
		{
			sb.append(objs[offset]);
			for (int i = 1; (i < len) && (i + offset < objs.length); i++)
				sb.append(c).append(objs[i + offset]);
		}
		return sb;
	}

	/**
	 * 将一个数组部分元素拼合成一个字符串
	 * 
	 * @param offset 开始元素的下标
	 * @param len 元素数量
	 * @param array 数组
	 * @return 拼合后的字符串
	 */
	public static <T> StringBuilder concat(final int offset, final int len, final T[] array)
	{
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < len; i++)
			sb.append(array[i + offset].toString());
		return sb;
	}

	/**
	 * 将一个集合转换成字符串
	 * <p>
	 * 每个元素之间，都会用一个给定的字符分隔
	 * 
	 * @param c 分隔符
	 * @param coll 集合
	 * @return 拼合后的字符串
	 */
	public static <T> StringBuilder concat(final Object c, final Collection<T> coll)
	{
		StringBuilder sb = new StringBuilder();
		if ((null == coll) || coll.isEmpty())
			return sb;
		Iterator<T> it = coll.iterator();
		sb.append(it.next());
		while (it.hasNext())
			sb.append(c).append(it.next());
		return sb;
	}

	/**
	 * 将一个整型数组转换成字符串
	 * <p>
	 * 每个元素之间，都会用一个给定的字符分隔
	 * 
	 * @param c 分隔符
	 * @param vals 数组
	 * @return 拼合后的字符串
	 */
	public static StringBuilder concat(final Object c, final int[] vals)
	{
		StringBuilder sb = new StringBuilder();
		if ((null == vals) || (0 == vals.length))
			return sb;

		sb.append(vals[0]);
		for (int i = 1; i < vals.length; i++)
			sb.append(c).append(vals[i]);

		return sb;
	}

	/**
	 * 将一个长整型数组转换成字符串
	 * <p>
	 * 每个元素之间，都会用一个给定的字符分隔
	 * 
	 * @param c 分隔符
	 * @param vals 数组
	 * @return 拼合后的字符串
	 */
	public static StringBuilder concat(final Object c, final long[] vals)
	{
		StringBuilder sb = new StringBuilder();
		if ((null == vals) || (0 == vals.length))
			return sb;

		sb.append(vals[0]);
		for (int i = 1; i < vals.length; i++)
			sb.append(c).append(vals[i]);

		return sb;
	}

	/**
	 * 将一个数组转换成字符串
	 * <p>
	 * 每个元素之间，都会用一个给定的字符分隔
	 * 
	 * @param c 分隔符
	 * @param objs 数组
	 * @return 拼合后的字符串
	 */
	public static <T> StringBuilder concat(final Object c, final T[] objs)
	{
		StringBuilder sb = new StringBuilder();
		if ((null == objs) || (0 == objs.length))
			return sb;

		sb.append(objs[0]);
		for (int i = 1; i < objs.length; i++)
			sb.append(c).append(objs[i]);

		return sb;
	}

	/**
	 * 将一个数组所有元素拼合成一个字符串
	 * 
	 * @param objs 数组
	 * @return 拼合后的字符串
	 */
	public static <T> StringBuilder concat(final T[] objs)
	{
		StringBuilder sb = new StringBuilder();
		for (T e : objs)
			sb.append(e.toString());
		return sb;
	}

	/**
	 * 将一个数组所有元素拼合成一个字符串，用指定的连接字符串连接
	 * 
	 * @param objs 数组
	 * @param split 连接字符串
	 * @return 拼合后的字符串
	 */
	public static <T> StringBuilder concat(final T[] objs, final String split)
	{
		StringBuilder sb = new StringBuilder();
		for (T e : objs)
		{
			if (sb.length() > 0)
				sb.append(split);
			sb.append(e.toString());
		}
		return sb;
	}

	/**
	 * 将一个数组指定数量的元素拼合成一个字符串
	 * 
	 * @param objs 数组
	 * @return 拼合后的字符串
	 */
	public static <T> StringBuilder concat(final T[] objs, final int num)
	{
		StringBuilder sb = new StringBuilder();
		if (num > objs.length - 1)
			return sb;
		for (int i = 0; i < num; i++)
			sb.append(objs[i].toString());
		return sb;
	}

	/**
	 * 将一个数组所有元素拼合成一个字符串，用指定的连接字符串连接
	 * 
	 * @param objs 数组
	 * @param split 连接字符串
	 * @return 拼合后的字符串
	 */
	public static <T> StringBuilder concat(final T[] objs, final int num, final String split)
	{
		StringBuilder sb = new StringBuilder();
		if (num > objs.length - 1)
			return sb;
		for (int i = 0; i < num; i++)
		{
			if (sb.length() > 0)
				sb.append(split);
			sb.append(objs[i].toString());
		}
		return sb;
	}

	/**
	 * 将一个数组转换成字符串
	 * <p>
	 * 所有的元素都被格式化字符串包裹。 这个格式话字符串只能有一个占位符， %s, %d 等，均可，请视你的数组内容而定
	 * <p>
	 * 每个元素之间，都会用一个给定的字符分隔
	 * 
	 * @param ptn 格式
	 * @param c 分隔符
	 * @param objs 数组
	 * @return 拼合后的字符串
	 */
	public static <T> StringBuilder concatBy(final String ptn, final Object c, final T[] objs)
	{
		StringBuilder sb = new StringBuilder();
		for (T obj : objs)
			sb.append(String.format(ptn, obj)).append(c);
		if (sb.length() > 0)
			sb.deleteCharAt(sb.length() - 1);
		return sb;
	}

	/**
	 * 将一个数组转换成字符串
	 * <p>
	 * 所有的元素都被格式化字符串包裹。 这个格式话字符串只能有一个占位符， %s, %d 等，均可，请视你的数组内容而定
	 * 
	 * @param fmt 格式
	 * @param objs 数组
	 * @return 拼合后的字符串
	 */
	public static <T> StringBuilder concatBy(final String fmt, final T[] objs)
	{
		StringBuilder sb = new StringBuilder();
		for (T obj : objs)
			sb.append(String.format(fmt, obj));
		return sb;
	}

	/**
	 * 判断一个数组内是否包括某一个对象。 它的比较将通过 equals(Object,Object) 方法
	 * 
	 * @param array 数组
	 * @param ele 对象
	 * @return true 包含 false 不包含
	 */
	public static <T> boolean contains(final T[] array, final T ele)
	{
		if (null == array)
			return false;
		for (T e : array)
			if (equals(e, ele))
				return true;
		return false;
	}

	private static <T extends Map<Object, Object>> Map<Object, Object> createMap(final Class<T> mapClass)
	{
		Map<Object, Object> map;
		try
		{
			map = mapClass.newInstance();
		}
		catch (Exception e)
		{
			map = new HashMap<Object, Object>();
		}
		if (!mapClass.isAssignableFrom(map.getClass()))
			throw Util.makeThrow("Fail to create map [%s]", mapClass.getName());
		return map;
	}

	/**
	 * 用回调的方式，遍历一个对象，可以支持遍历
	 * <ul>
	 * <li>数组
	 * <li>集合
	 * <li>Map
	 * <li>单一元素
	 * </ul>
	 * 
	 * @param obj 对象
	 * @param callback 回调
	 */
	@SuppressWarnings({ "unchecked" })
	public static <T> void each(final Object obj, final IEach<T> callback)
	{
		if ((null == obj) || (null == callback))
			return;
		try
		{
			Class<T>[] typeParams = (Class<T>[]) Mirror.getTypeParams(callback.getClass());
			Class<T> eType = null;
			if ((typeParams != null) && (typeParams.length > 0))
				eType = typeParams[0];
			if (obj.getClass().isArray())
			{
				int len = Array.getLength(obj);
				for (int i = 0; i < len; i++)
					try
					{
						callback.invoke(i, (T) Array.get(obj, i), len);
					}
					catch (ExitLoopException e)
					{
						break;
					}
			}
			else if (obj instanceof Collection)
			{
				int len = ((Collection<T>) obj).size();
				int i = 0;
				for (Iterator<T> it = ((Collection<T>) obj).iterator(); it.hasNext();)
					try
					{
						callback.invoke(i++, it.next(), len);
					}
					catch (ExitLoopException e)
					{
						break;
					}
			}
			else if (obj instanceof Map)
			{
				Map<?, ?> map = (Map<?, ?>) obj;
				int len = map.size();
				int i = 0;
				if ((null != eType) && eType.isAssignableFrom(Entry.class))
					for (Object v : map.entrySet())
						try
						{
							callback.invoke(i++, (T) v, len);
						}
						catch (ExitLoopException e)
						{
							break;
						}
				else
					for (Object v : map.entrySet())
						try
						{
							callback.invoke(i++, (T) ((Entry<?, ?>) v).getValue(), len);
						}
						catch (ExitLoopException e)
						{
							break;
						}
			}
			else
				try
				{
					callback.invoke(0, (T) obj, 1);
				}
				catch (ExitLoopException e)
				{
				}
		}
		catch (LoopException e)
		{
			throw Util.wrapThrow(e.getCause());
		}
	}

	/**
	 * 返回一个集合对象的枚举对象。实际上就是对 Iterator 接口的一个封装
	 * 
	 * @param col 集合对象
	 * @return 枚举对象
	 */
	public static <T> Enumeration<T> enumeration(final Collection<T> col)
	{
		final Iterator<T> it = col.iterator();
		return new Enumeration<T>()
		{
			public boolean hasMoreElements()
			{
				return it.hasNext();
			}

			public T nextElement()
			{
				return it.next();
			}
		};
	}

	/**
	 * 判断两个对象是否相等。 这个函数用处是:
	 * <ul>
	 * <li>可以容忍 null
	 * <li>可以容忍不同类型的 Number
	 * <li>对数组，集合， Map 会深层比较
	 * </ul>
	 * 当然，如果你重写的 equals 方法会优先
	 * 
	 * @param a1 比较对象1
	 * @param a2 比较对象2
	 * @return 是否相等
	 */
	@SuppressWarnings("unchecked")
	public static boolean equals(final Object a1, final Object a2)
	{
		if (a1 == a2)
			return true;
		if ((a1 == null) || (a2 == null))
			return false;
		if (a1.equals(a2))
			return true;
		if (a1 instanceof Number)
			return (a2 instanceof Number) && a1.toString().equals(a2.toString());
		if ((a1 instanceof Map) && (a2 instanceof Map))
		{
			Map<?, ?> m1 = (Map<?, ?>) a1;
			Map<?, ?> m2 = (Map<?, ?>) a2;
			if (m1.size() != m2.size())
				return false;
			for (Entry<?, ?> e : m1.entrySet())
			{
				Object key = e.getKey();
				if (!m2.containsKey(key) || !equals(m1.get(key), m2.get(key)))
					return false;
			}
			return true;
		}
		else if (a1.getClass().isArray())
		{
			if (a2.getClass().isArray())
			{
				int len = Array.getLength(a1);
				if (len != Array.getLength(a2))
					return false;
				for (int i = 0; i < len; i++)
					if (!equals(Array.get(a1, i), Array.get(a2, i)))
						return false;
				return true;
			}
			else if (a2 instanceof List)
				return equals(a1, Util.collection2array((List<Object>) a2, Object.class));
			return false;
		}
		else if (a1 instanceof List)
		{
			if (a2 instanceof List)
			{
				List<?> l1 = (List<?>) a1;
				List<?> l2 = (List<?>) a2;
				if (l1.size() != l2.size())
					return false;
				int i = 0;
				for (Object name : l1)
					if (!equals(name, l2.get(i++)))
						return false;
				return true;
			}
			else if (a2.getClass().isArray())
				return equals(Util.collection2array((List<Object>) a1, Object.class), a2);
			return false;
		}
		else if ((a1 instanceof Collection) && (a2 instanceof Collection))
		{
			Collection<?> c1 = (Collection<?>) a1;
			Collection<?> c2 = (Collection<?>) a2;
			if (c1.size() != c2.size())
				return false;
			return c1.containsAll(c2) && c2.containsAll(c1);
		}
		return false;
	}

	/**
	 * 将一个或者多个数组填入一个集合。
	 * 
	 * @param <C> 集合类型
	 * @param <T> 数组元素类型
	 * @param coll 集合
	 * @param objss 数组 （数目可变）
	 * @return 集合对象
	 */
	public static <C extends Collection<T>, T> C fill(final C coll, final T[]... objss)
	{
		for (T[] objs : objss)
			for (T obj : objs)
				coll.add(obj);
		return coll;
	}

	/**
	 * 获取集合中的第一个元素，如果集合为空，返回 null
	 * 
	 * @param coll 集合
	 * @return 第一个元素
	 */
	public static <T> T first(final Collection<T> coll)
	{
		if ((null == coll) || coll.isEmpty())
			return null;
		return coll.iterator().next();
	}

	/**
	 * 获得表中的第一个名值对
	 * 
	 * @param map 表
	 * @return 第一个名值对
	 */
	public static <K, V> Entry<K, V> first(final Map<K, V> map)
	{
		if ((null == map) || map.isEmpty())
			return null;
		return map.entrySet().iterator().next();
	}

	/**
	 * 根据一段文本模拟出一个文本输入流对象
	 * 
	 * @param cs 文本
	 * @return 文本输出流对象
	 */
	public static Reader inr(final CharSequence cs)
	{
		return new StringReader(cs);
	}

	/**
	 * 根据一段文本模拟出一个输入流对象 <br/>
	 * 
	 * @param cs 文本
	 * @return 输出流对象
	 */
	public static InputStream ins(final CharSequence cs)
	{
		return new StringInputStream(cs);
	}

	/**
	 * 判断当前系统是否为Windows
	 * 
	 * @return true 如果当前系统为Windows系统
	 */
	public static boolean isWin()
	{
		try
		{
			String os = System.getenv("OS");
			return (os != null) && (os.indexOf("Windows") > -1);
		}
		catch (Throwable e)
		{
			return false;
		}
	}

	/**
	 * 根据格式化字符串，生成一个指定的异常。
	 * 
	 * @param classOfT 异常类型， 需要有一个字符串为参数的构造函数
	 * @param format 格式
	 * @param args 参数
	 * @return 异常对象
	 */
	@SuppressWarnings("unchecked")
	public static <T extends Exception> T makeThrow(final Class<T> classOfT, final String format, final Object... args)
	{
		T t = (T) new AppException("ERR-" + classOfT.getSimpleName(), String.format(format, args));
		return t;
	}

	/**
	 * 根据格式化字符串，生成运行时异常
	 * 
	 * @param format 格式
	 * @param args 参数
	 * @return 运行时异常
	 */
	public static RuntimeException makeThrow(final String format, final Object... args)
	{
		return new RuntimeException(String.format(format, args));
	}

	/**
	 * 根据一个 Map，和给定的对象类型，创建一个新的 JAVA 对象
	 * 
	 * @param src Map 对象
	 * @param toType JAVA 对象类型
	 * @return JAVA 对象
	 * @throws FailToCastObjectException
	 * @throws InvocationTargetException
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 * @throws IllegalArgumentException
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static <T> T map2Object(final Map<?, ?> src, final Class<T> toType) throws FailToCastObjectException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException
	{
		if (null == toType)
			throw new FailToCastObjectException("target type is Null");
		if (toType == Map.class)
			return (T) src;
		if (Map.class.isAssignableFrom(toType))
		{
			Map map;
			try
			{
				map = (Map) toType.newInstance();
				map.putAll(src);
				return (T) map;
			}
			catch (Exception e)
			{
				throw new FailToCastObjectException("target type fail to born!");
			}

		}
		Mirror<T> mirror = Mirror.me(toType);
		T obj = mirror.born();
		for (Field field : mirror.getFields())
		{
			Object v = src.get(field.getName());
			Object vv = Castors.me().castTo(v, field.getType());
			mirror.setValue(obj, field, vv);
		}
		return obj;
	}

	/**
	 * 将多个数组，合并成一个数组。如果这些数组为空，则返回 null
	 * 
	 * @param arys 数组对象
	 * @return 合并后的数组对象
	 */
	@SuppressWarnings("unchecked")
	public static <T> T[] merge(final T[]... arys)
	{
		Queue<T> list = new LinkedList<T>();
		for (T[] ary : arys)
			if (null != ary)
				for (T e : ary)
					if (null != e)
						list.add(e);
		if (list.isEmpty())
			return null;
		Class<T> type = (Class<T>) list.peek().getClass();
		return list.toArray((T[]) Array.newInstance(type, list.size()));
	}

	/**
	 * @return 一个未实现的运行时异常
	 */
	public static RuntimeException noImplement()
	{
		return new RuntimeException("Not implement yet!");
	}

	/**
	 * Throw an IllegalArgumentException if the argument is null, otherwise just return the argument. Useful for assignment as
	 * in this.thing = Utils.notNull(thing);
	 * 
	 * @param <T> The type of the thing
	 * @param t The thing to check for nullness.
	 */
	public static <T> T notNull(final T t)
	{
		if (t == null)
			throw new IllegalArgumentException("This object MUST be non-null.");
		return t;
	}

	/**
	 * Throw an IllegalArgumentException if the argument is null, otherwise just return the argument. Useful for assignment as
	 * in this.thing = Utils.notNull(thing);
	 * 
	 * @param <T> The type of the thing
	 * @param t The thing to check for nullness.
	 * @param message The message to put in the exception if it is null
	 */
	public static <T> T notNull(final T t, final String message)
	{
		if (t == null)
			throw new IllegalArgumentException(message);
		return t;
	}

	/**
	 * 将对象转换成 Map
	 * 
	 * @param obj POJO 对象
	 * @return Map 对象
	 */
	@SuppressWarnings("unchecked")
	public static Map<String, Object> obj2map(final Object obj)
	{
		return obj2map(obj, HashMap.class);
	}

	/**
	 * 将对象转换成 Map
	 * 
	 * @param <T>
	 * @param obj POJO 对象
	 * @param mapType Map 的类型
	 * @return Map 对象
	 */
	public static <T extends Map<String, Object>> T obj2map(final Object obj, final Class<T> mapType)
	{
		try
		{
			T map = mapType.newInstance();
			Util.obj2map(obj, map, new HashMap<Object, Object>());
			return map;
		}
		catch (Exception e)
		{
			throw Util.wrapThrow(e);
		}
	}

	@SuppressWarnings("unchecked")
	private static <T extends Map<String, Object>> void obj2map(final Object obj, final T map, final Map<Object, Object> memo)
	{
		if ((null == obj) || memo.containsKey(obj))
			return;
		memo.put(obj, "");

		Mirror<?> mirror = Mirror.me(obj.getClass());
		Field[] flds = mirror.getFields();
		for (Field fld : flds)
		{
			Object v = mirror.getValue(obj, fld);
			if (null == v)
				map.put(fld.getName(), null);
			Mirror<?> mr = Mirror.me(fld.getType());
			if (mr.isNumber() || mr.isBoolean() || mr.isChar() || mr.isStringLike() || mr.isDateTimeLike())
				map.put(fld.getName(), v);
			else if (memo.containsKey(v))
				map.put(fld.getName(), null);
			else
			{
				T sub;
				try
				{
					sub = (T) map.getClass().newInstance();
				}
				catch (Exception e)
				{
					throw Util.wrapThrow(e);
				}
				obj2map(v, sub, memo);
				map.put(fld.getName(), sub);
			}
		}
	}

	/**
	 * 根据一个 StringBuilder 模拟一个输出流对象
	 * 
	 * @param sb StringBuilder 对象
	 * @return 输出流对象
	 */
	public static StringOutputStream ops(final StringBuilder sb)
	{
		return new StringOutputStream(sb);
	}

	/**
	 * 根据一个 StringBuilder 模拟一个文本输出流对象
	 * 
	 * @param sb StringBuilder 对象
	 * @return 文本输出流对象
	 */
	public static Writer opw(final StringBuilder sb)
	{
		return new StringWriter(sb);
	}

	/**
	 * 将字符串解析成 boolean 值，支持更多的字符串
	 * <ul>
	 * <li>1 | 0
	 * <li>yes | no
	 * <li>on | off
	 * <li>true | false
	 * </ul>
	 * 
	 * @param s
	 * @return 布尔值
	 */
	public static boolean parseBoolean(String s)
	{
		if ((null == s) || (s.length() == 0))
			return false;
		if (s.length() > 5)
			return true;
		if ("0".equals(s))
			return false;
		s = s.toLowerCase();
		return !"false".equals(s) && !"off".equals(s) && !"no".equals(s);
	}

	/**
	 * 从一个文本输入流读取所有内容，并将该流关闭
	 * 
	 * @param reader 文本输入流
	 * @return 输入流所有内容
	 */
	public static String readAll(Reader reader)
	{
		if (!(reader instanceof BufferedReader))
			reader = new BufferedReader(reader);
		try
		{
			StringBuilder sb = new StringBuilder();

			char[] data = new char[64];
			int len;
			while (true)
			{
				if ((len = reader.read(data)) == -1)
					break;
				sb.append(data, 0, len);
			}
			return sb.toString();
		}
		catch (IOException e)
		{
			throw wrapThrow(e);
		}
		finally
		{
			Streams.safeClose(reader);
		}
	}

	/**
	 * 测试一个对象是否 == Null。
	 * 
	 * @param owner 被测试对象拥有者，一般在实例方法中，直接用“this”即可。
	 * @param row 代码所在行号,便于查找。
	 * @param testObject 被测试的对象
	 */
	public static void testIsNull(final Object owner, final int row, final Object testObject)
	{
		Sber sber = Sber.ME();
		sber.append(">>> 测试,代码约在").append(row).append("行。在:").append(owner.getClass().getSimpleName()).append("类中。经测试,目标:");
		if (null != testObject)
			sber.append("不为Null。-->> ").append(testObject.getClass().getSimpleName());
		else
			sber.append("为Null。");
		System.out.println(sber.toString());
	}

	/**
	 * 将字符数组强制转换成字节数组。如果字符为双字节编码，则会丢失信息
	 * 
	 * @param cs 字符数组
	 * @return 字节数组
	 */
	public static byte[] toBytes(final char[] cs)
	{
		byte[] bs = new byte[cs.length];
		for (int i = 0; i < cs.length; i++)
			bs[i] = (byte) cs[i];
		return bs;
	}

	/**
	 * 将整数数组强制转换成字节数组。整数的高位将会被丢失
	 * 
	 * @param is 整数数组
	 * @return 字节数组
	 */
	public static byte[] toBytes(final int[] is)
	{
		byte[] bs = new byte[is.length];
		for (int i = 0; i < is.length; i++)
			bs[i] = (byte) is[i];
		return bs;
	}

	public static Throwable unwrapThrow(final Throwable e)
	{
		if (e == null)
			return null;
		if (e instanceof InvocationTargetException)
		{
			InvocationTargetException itE = (InvocationTargetException) e;
			if (itE.getTargetException() != null)
				return unwrapThrow(itE.getTargetException());
		}
		if (e.getCause() != null)
			return unwrapThrow(e.getCause());
		return e;
	}

	/**
	 * 用运行时异常包裹抛出对象，如果抛出对象本身就是运行时异常，则直接返回。
	 * <p>
	 * 如果是 InvocationTargetException，那么将其剥离，只包裹其 TargetException
	 * 
	 * @param e 抛出对象
	 * @return 运行时异常
	 */
	public static RuntimeException wrapThrow(final Throwable e)
	{
		if (e instanceof RuntimeException)
			return (RuntimeException) e;
		if (e instanceof InvocationTargetException)
			return wrapThrow(((InvocationTargetException) e).getTargetException());
		return new RuntimeException(e);
	}

	/**
	 * 将抛出对象包裹成运行时异常，并增加自己的描述
	 * 
	 * @param e 抛出对象
	 * @param fmt 格式
	 * @param args 参数
	 * @return 运行时异常
	 */
	public static RuntimeException wrapThrow(final Throwable e, final String fmt, final Object... args)
	{
		return new RuntimeException(String.format(fmt, args), e);
	}

	/**
	 * 将一段字符串写入一个文本输出流，并将该流关闭
	 * 
	 * @param writer 文本输出流
	 * @param str 字符串
	 */
	public static void writeAll(final Writer writer, final String str)
	{
		try
		{
			writer.write(str);
			writer.flush();
		}
		catch (IOException e)
		{
			throw Util.wrapThrow(e);
		}
		finally
		{
			Streams.safeClose(writer);
		}
	}

	/**
	 * 帮你快速获得一个 DocumentBuilder，方便 XML 解析。
	 * 
	 * @return 一个 DocumentBuilder 对象
	 * @throws ParserConfigurationException
	 */
	public static DocumentBuilder xmls() throws ParserConfigurationException
	{
		return DocumentBuilderFactory.newInstance().newDocumentBuilder();
	}

	/**
	 * 对Thread.sleep(long)的简单封装,不抛出任何异常
	 * 
	 * @param millisecond 休眠时间
	 */
	public void quiteSleep(final long millisecond)
	{
		try
		{
			if (millisecond > 0)
				Thread.sleep(millisecond);
		}
		catch (Throwable e)
		{
		}
	}

	/**
	 * 在控制台打印标记以显示进展状态。
	 * 
	 * @param display 以多少为一个步进。
	 */
	public static void printProgress(final int display)
	{
		// if (point / (60 * display) == 1)
		// {
		// point = 0;
		// System.out.println();
		// }
		// if (point % display == 0)
		// System.out.print('-');
		// point++;
	}

	/**
	 * 启动一个计时器
	 */
	public static void startWatch()
	{
		stopwatch.reset();
		stopwatch.start();
	}

	public static void stopWatch()
	{
		stopwatch.stop();
	}

	public static long getWatch()
	{
		stopwatch.stop();
		long o = stopwatch.getTime();
		return o;
	}

	/**
	 * 打印消耗时间
	 */
	public static void printWatch()
	{
		System.out.println("耗时：" + Util.getWatch() + "毫秒");
	}

	/**
	 * 输入的字符串是否是一个数字
	 * @param number
	 * @return
	 */
	public static boolean isNumber(String number)
	{
		try
		{
			Float.parseFloat(number);
		}
		catch (Exception e)
		{
			return false;
		}
		return true;
	}

	private static StopWatch stopwatch = new StopWatch();

	public final static char[] UUIDChar = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'r' };

}
